﻿/********************************************************************************
** 作者： Mick
** 邮箱： zheng_jinfan@126.com
** 主页： http://www.zhengjinfan.cn
** 创始时间：2016-3-25
** 描述：
**      数据库基类接口，…
*********************************************************************************/
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq.Expressions;
using System.Threading.Tasks;
using NPoco;
using NPoco.Linq;

namespace BestEasy.NPoco
{
    /// <summary>
    /// 数据访问接口
    /// </summary>
    public interface IDbBase
    {
        /// <summary>
        /// 打开共享连接
        /// </summary>
        void OpenSharedConnection();
        /// <summary>
        /// 关闭共享连接
        /// </summary>
        void CloseSharedConnection();
        /// <summary>
        /// 执行Sql语句
        /// </summary>
        /// <param name="sql">sql语句</param>
        /// <param name="args">参数</param>
        /// <returns>受影响行数</returns>
        int Execute(string sql, params object[] args);
        int Execute(Sql sql);
        Task<int> ExecuteAsync(string sql, params object[] args);
        Task<int> ExecuteAsync(Sql sql);
        /// <summary>
        /// 执行Sql语句
        /// </summary>
        /// <typeparam name="T">返回类型</typeparam>
        /// <param name="sql">sql</param>
        /// <param name="args">参数</param>
        /// <returns>返回结果集中第一行的第一列</returns>
        T ExecuteScalar<T>(string sql, params object[] args);
        T ExecuteScalar<T>(Sql sql);
        Task<T> ExecuteScalarAsync<T>(string sql, params object[] args);
        Task<T> ExecuteScalarAsync<T>(Sql sql);
        /// <summary>
        /// 获取实体对象的所有信息
        /// </summary>
        /// <typeparam name="T">实体对象类型</typeparam>
        /// <returns>结果集</returns>
        List<T> Fetch<T>();
        /// <summary>
        /// 获取实体对象列表
        /// </summary>
        /// <typeparam name="T">实体对象类型</typeparam>
        /// <param name="sql">sql语句</param>
        /// <param name="args">参数</param>
        /// <returns>结果集</returns>
        List<T> Fetch<T>(string sql, params object[] args);
        List<T> Fetch<T>(Sql sql);
        Task<List<T>> FetchAsync<T>(string sql, params object[] args);
        Task<List<T>> FetchAsync<T>(Sql sql);
        /// <summary>
        /// 获取分页数据
        /// </summary>
        /// <typeparam name="T">实体对象类型</typeparam>
        /// <param name="page">当前页码</param>
        /// <param name="itemsPerPage">每页的记录数</param>
        /// <param name="sql">sql语句</param>
        /// <param name="args">参数</param>
        /// <returns>结果集</returns>
        List<T> Fetch<T>(long page, long itemsPerPage, string sql, params object[] args);
        List<T> Fetch<T>(long page, long itemsPerPage, Sql sql);
        Task<List<T>> FetchAsync<T>(long page, long itemsPerPage, string sql, params object[] args);
        Task<List<T>> FetchAsync<T>(long page, long itemsPerPage, Sql sql);
        /// <summary>
        /// 获取分页数据
        /// </summary>
        /// <typeparam name="T">实体对象类型</typeparam>
        /// <param name="page">当前页码</param>
        /// <param name="itemsPerPage">每页的记录数</param>
        /// <param name="sql">sql语句</param>
        /// <param name="args">参数</param>
        /// <returns>Page对象</returns>
        Page<T> Page<T>(long page, long itemsPerPage, string sql, params object[] args);
        Page<T> Page<T>(long page, long itemsPerPage, Sql sql);
        Task<Page<T>> PageAsync<T>(long page, long itemsPerPage, string sql, params object[] args);
        Task<Page<T>> PageAsync<T>(long page, long itemsPerPage, Sql sql);
        List<T> SkipTake<T>(long skip, long take, string sql, params object[] args);
        List<T> SkipTake<T>(long skip, long take, Sql sql);
        Task<List<T>> SkipTakeAsync<T>(long skip, long take, string sql, params object[] args);
        Task<List<T>> SkipTakeAsync<T>(long skip, long take, Sql sql);
        IEnumerable<T> Query<T>(string sql, params object[] args);
        IEnumerable<T> Query<T>(Sql sql);
        Task<IEnumerable<T>> QueryAsync<T>(string sql, params object[] args);
        Task<IEnumerable<T>> QueryAsync<T>(Sql sql);
        /// <summary>
        /// Linq 查询
        /// </summary>
        /// <typeparam name="T">实体对象类型</typeparam>
        /// <returns></returns>
        IQueryProviderWithIncludes<T> Query<T>();
        /// <summary>
        /// 获取单个对象
        /// </summary>
        /// <typeparam name="T">实体对象类型</typeparam>
        /// <param name="primaryKey">主键</param>
        /// <returns></returns>
        T SingleById<T>(object primaryKey);
        Task<T> SingleByIdAsync<T>(object primaryKey);
        /// <summary>
        /// 获取单个对象
        /// </summary>
        /// <typeparam name="T">实体对象类型</typeparam>
        /// <param name="primaryKey">主键</param>
        /// <returns></returns>
        T SingleOrDefaultById<T>(object primaryKey);
        Task<T> SingleOrDefaultByIdAsync<T>(object primaryKey);
        /// <summary>
        /// 获取单个对象
        /// </summary>
        /// <typeparam name="T">实体对象类型</typeparam>
        /// <param name="sql">sql语句</param>
        /// <param name="args">参数</param>
        /// <returns></returns>
        T Single<T>(string sql, params object[] args);
        T Single<T>(Sql sql);
        T SingleInto<T>(T instance, string sql, params object[] args);
        T SingleInto<T>(T instance, Sql sql);
        T SingleOrDefault<T>(string sql, params object[] args);
        T SingleOrDefault<T>(Sql sql);
        T SingleOrDefaultInto<T>(T instance, string sql, params object[] args);
        T SingleOrDefaultInto<T>(T instance, Sql sql);
        T First<T>(string sql, params object[] args);
        T First<T>(Sql sql);
        T FirstInto<T>(T instance, string sql, params object[] args);
        T FirstInto<T>(T instance, Sql sql);
        T FirstOrDefault<T>(string sql, params object[] args);
        T FirstOrDefault<T>(Sql sql);
        T FirstOrDefaultInto<T>(T instance, string sql, params object[] args);
        T FirstOrDefaultInto<T>(T instance, Sql sql);

        Dictionary<TKey, TValue> Dictionary<TKey, TValue>(Sql sql);
        Dictionary<TKey, TValue> Dictionary<TKey, TValue>(string sql, params object[] args);
        /// <summary>
        /// 查询数据记录是否存在
        /// </summary>
        /// <typeparam name="T">实体对象类型</typeparam>
        /// <param name="primaryKey">主键</param>
        /// <returns></returns>
        bool Exists<T>(object primaryKey);

        TRet FetchMultiple<T1, T2, TRet>(Func<List<T1>, List<T2>, TRet> cb, string sql, params object[] args);
        TRet FetchMultiple<T1, T2, T3, TRet>(Func<List<T1>, List<T2>, List<T3>, TRet> cb, string sql, params object[] args);
        TRet FetchMultiple<T1, T2, T3, T4, TRet>(Func<List<T1>, List<T2>, List<T3>, List<T4>, TRet> cb, string sql, params object[] args);
        TRet FetchMultiple<T1, T2, TRet>(Func<List<T1>, List<T2>, TRet> cb, Sql sql);
        TRet FetchMultiple<T1, T2, T3, TRet>(Func<List<T1>, List<T2>, List<T3>, TRet> cb, Sql sql);
        TRet FetchMultiple<T1, T2, T3, T4, TRet>(Func<List<T1>, List<T2>, List<T3>, List<T4>, TRet> cb, Sql sql);

        Tuple<List<T1>, List<T2>> FetchMultiple<T1, T2>(string sql, params object[] args);
        Tuple<List<T1>, List<T2>, List<T3>> FetchMultiple<T1, T2, T3>(string sql, params object[] args);
        Tuple<List<T1>, List<T2>, List<T3>, List<T4>> FetchMultiple<T1, T2, T3, T4>(string sql, params object[] args);
        Tuple<List<T1>, List<T2>> FetchMultiple<T1, T2>(Sql sql);
        Tuple<List<T1>, List<T2>, List<T3>> FetchMultiple<T1, T2, T3>(Sql sql);
        Tuple<List<T1>, List<T2>, List<T3>, List<T4>> FetchMultiple<T1, T2, T3, T4>(Sql sql);

        IDataParameter CreateParameter();
        void AddParameter(DbCommand cmd, object value);
        IDbCommand CreateCommand(DbConnection connection, string sql, params object[] args);
        /// <summary>
        /// 获取一个事务
        /// </summary>
        /// <returns></returns>
        ITransaction GetTransaction();
        /// <summary>
        /// 获取一个事务
        /// </summary>
        /// <param name="isolationLevel">指定连接的事务锁定行为</param>
        /// <returns></returns>
        ITransaction GetTransaction(IsolationLevel isolationLevel);
        void SetTransaction(DbTransaction tran);
        /// <summary>
        /// 开始事务
        /// </summary>
        void BeginTransaction();
        /// <summary>
        /// 开始事务
        /// </summary>
        /// <param name="isolationLevel">指定连接的事务锁定行为</param>
        void BeginTransaction(IsolationLevel isolationLevel);
        /// <summary>
        /// 事务中止
        /// </summary>
        void AbortTransaction();
        /// <summary>
        /// 事务完成
        /// </summary>
        void CompleteTransaction();
        /// <summary>
        /// 插入一条记录
        /// </summary>
        /// <typeparam name="T">实体对象类型</typeparam>
        /// <param name="tableName">表名</param>
        /// <param name="primaryKeyName">主键名</param>
        /// <param name="autoIncrement">是否为自增</param>
        /// <param name="poco">实体</param>
        /// <returns></returns>
        object Insert<T>(string tableName, string primaryKeyName, bool autoIncrement, T poco);
        /// <summary>
        /// 插入一条记录
        /// </summary>
        /// <typeparam name="T">实体对象类型</typeparam>
        /// <param name="tableName">表名</param>
        /// <param name="primaryKeyName">主键名</param>
        /// <param name="poco">实体</param>
        /// <returns></returns>
        object Insert<T>(string tableName, string primaryKeyName, T poco);
        /// <summary>
        /// 插入一条记录
        /// </summary>
        /// <typeparam name="T">实体对象类型</typeparam>
        /// <param name="poco">实体</param>
        /// <returns>主键ID</returns>
        object Insert<T>(T poco);
        Task<object> InsertAsync<T>(T poco);
        /// <summary>
        /// 插入多条记录
        /// </summary>
        /// <typeparam name="T">实体对象类型</typeparam>
        /// <param name="pocos">实体集合</param>
        void InsertBulk<T>(IEnumerable<T> pocos);
        /// <summary>
        /// 更新一条数据
        /// </summary>
        /// <param name="tableName">表名</param>
        /// <param name="primaryKeyName">主键名</param>
        /// <param name="poco">实体</param>
        /// <param name="primaryKeyValue">主键值</param>
        /// <returns>受影响行数</returns>
        int Update(string tableName, string primaryKeyName, object poco, object primaryKeyValue);
        /// <summary>
        /// 更新一条数据
        /// </summary>
        /// <param name="tableName">表名</param>
        /// <param name="primaryKeyName">主键名</param>
        /// <param name="poco">实体</param>
        /// <returns>受影响行数</returns>
        int Update(string tableName, string primaryKeyName, object poco);
        /// <summary>
        /// 更新一条数据
        /// </summary>
        /// <param name="tableName">表名</param>
        /// <param name="primaryKeyName">主键名</param>
        /// <param name="poco">实体</param>
        /// <param name="primaryKeyValue">主键值</param>
        /// <param name="columns">要更新的字段</param>
        /// <returns>受影响行数</returns>
        int Update(string tableName, string primaryKeyName, object poco, object primaryKeyValue, IEnumerable<string> columns);
        /// <summary>
        /// 更新一条数据
        /// </summary>
        /// <param name="tableName">表名</param>
        /// <param name="primaryKeyName">主键名</param>
        /// <param name="poco">实体</param>
        /// <param name="columns">要更新的字段</param>
        /// <returns>受影响行数</returns>
        int Update(string tableName, string primaryKeyName, object poco, IEnumerable<string> columns);
        /// <summary>
        /// 更新一条数据
        /// </summary>
        /// <param name="poco">实体</param>
        /// <param name="columns">要更新的字段</param>
        /// <returns>受影响行数</returns>
        int Update(object poco, IEnumerable<string> columns);
        /// <summary>
        /// 更新一条数据
        /// </summary>
        /// <param name="poco">实体</param>
        /// <param name="primaryKeyValue">主键值</param>
        /// <param name="columns">要更新的字段</param>
        /// <returns>受影响行数</returns>
        int Update(object poco, object primaryKeyValue, IEnumerable<string> columns);
        /// <summary>
        /// 更新一条数据
        /// </summary>
        /// <param name="poco">实体</param>
        /// <returns>受影响行数</returns>
        int Update(object poco);
        Task<int> UpdateAsync(object poco);
        /// <summary>
        /// 更新一条数据
        /// </summary>
        /// <typeparam name="T">实体对象类型</typeparam>
        /// <param name="poco">实体</param>
        /// <param name="fields"></param>
        /// <returns>受影响行数</returns>
        int Update<T>(T poco, Expression<Func<T, object>> fields);
        /// <summary>
        /// 更新一条数据
        /// </summary>
        /// <param name="poco">实体</param>
        /// <param name="primaryKeyValue">主键值</param>
        /// <returns>受影响行数</returns>
        int Update(object poco, object primaryKeyValue);
        /// <summary>
        /// 更新一条数据
        /// </summary>
        /// <typeparam name="T">实体对象类型</typeparam>
        /// <param name="sql">sql语句</param>
        /// <param name="args">参数</param>
        /// <returns>受影响行数</returns>
        int Update<T>(string sql, params object[] args);
        /// <summary>
        /// 更新一条数据
        /// </summary>
        /// <typeparam name="T">实体对象类型</typeparam>
        /// <param name="sql">sql</param>
        /// <returns></returns>
        int Update<T>(Sql sql);
        /// <summary>
        /// Linq 写法 更新数据
        /// </summary>
        /// <typeparam name="T">实体对象类型</typeparam>
        /// <returns></returns>
        IUpdateQueryProvider<T> UpdateMany<T>();
        int Delete(string tableName, string primaryKeyName, object poco);
        int Delete(string tableName, string primaryKeyName, object poco, object primaryKeyValue);
        int Delete(object poco);
        Task<int> DeleteAsync(object poco);
        int Delete<T>(string sql, params object[] args);
        int Delete<T>(Sql sql);
        /// <summary>
        /// 删除一条记录
        /// </summary>
        /// <typeparam name="T">实体对象类型</typeparam>
        /// <param name="pocoOrPrimaryKey">主键</param>
        /// <returns></returns>
        int Delete<T>(object pocoOrPrimaryKey);
        /// <summary>
        ///  Linq 写法 删除数据
        /// </summary>
        /// <typeparam name="T">实体对象类型</typeparam>
        /// <returns></returns>
        IDeleteQueryProvider<T> DeleteMany<T>();
        /// <summary>
        /// 保存一条记录[插入或更新] 
        /// </summary>
        /// <typeparam name="T">实体对象类型</typeparam>
        /// <param name="poco">实体</param>
        void Save<T>(T poco);
        /// <summary>
        /// 是否为新数据
        /// </summary>
        /// <typeparam name="T">实体对象类型</typeparam>
        /// <param name="poco">实体</param>
        /// <returns></returns>
        bool IsNew<T>(T poco);

    }
}
